package nl.runnable.solr.util;

import java.io.File;
import java.net.URI;
import java.util.Map;

import org.apache.solr.common.ResourceLoader;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.XmlUpdateRequestHandler;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;

/**
 * Helper for {@link SolrRequestHandler} operations.
 * 
 * @author Laurens Fridael
 * 
 */
public class RequestHandlerHelper {

	/**
	 * Obtains the first a {@link SolrRequestHandler} a given type using the given {@link SolrQueryRequest}. This
	 * implementation returns the first available result.
	 * 
	 * @param request
	 * @param type
	 *            The type of {@link SolrRequestHandler}.
	 * @return The matching {@link SolrRequestHandler} or null if none could be found.
	 */
	@SuppressWarnings("unchecked")
	public <RequestHandlerType extends SolrRequestHandler> RequestHandlerType getRequestHandler(
			final SolrQueryRequest request, final Class<RequestHandlerType> type) {
		if (request == null) {
			throw new IllegalArgumentException("SolrQueryRequest cannot be null.");
		}
		if (type == null) {
			throw new IllegalArgumentException("Class cannot be null.");
		}

		final Map<String, RequestHandlerType> requestHandlers = (Map<String, RequestHandlerType>) request.getCore()
				.getRequestHandlers(XmlUpdateRequestHandler.class);
		RequestHandlerType requestHandler = null;
		if (requestHandlers.isEmpty() == false) {
			requestHandler = selectRequestHandler(requestHandlers, type);
		}
		return requestHandler;
	}

	/**
	 * Selects a {@link SolrRequestHandler} from the given {@link Map} of potential candidates. This implementation
	 * simply selects the first {@link SolrRequestHandler} available. Subclasses may provide a different implementation.
	 * 
	 * @param requestHandlers
	 *            The available {@link SolrRequestHandler}s. Should never be empty.
	 * @param type
	 *            The type requested. This implementation does not actually use this argument.
	 * @return The {@link SolrRequestHandler}.
	 */
	protected <RequestHandlerType extends SolrRequestHandler> RequestHandlerType selectRequestHandler(
			final Map<String, RequestHandlerType> requestHandlers, final Class<RequestHandlerType> type) {
		return requestHandlers.values().iterator().next();
	}

	/**
	 * Obtains the {@link ResourceLoader} from the {@link SolrQueryRequest}. This implementation simply calls
	 * {@link SolrCore#getResourceLoader()}
	 * <p>
	 * The main reason for this method's existence is to be able to mock/spy this method during a unit test. The
	 * {@link SolrCore} class cannot be easily mocked because it is declared as final.
	 * 
	 * @param request
	 * @return
	 */
	public ResourceLoader getResourceLoader(final SolrQueryRequest request) {
		if (request == null) {
			throw new IllegalArgumentException("SolrQueryRequest cannot be null.");
		}
		return request.getCore().getResourceLoader();
	}

	/**
	 * Obtains a resource using a given {@link SolrQueryRequest}. This implementation attempts to resolve the resource
	 * against the data directory provided by {@link SolrCore#getDataDir()}.
	 * 
	 * @param request
	 * @return
	 */
	public URI getResource(final SolrQueryRequest request, final String resource) {
		final File directory = new File(request.getCore().getDataDir());
		final File file = new File(directory, resource);
		URI uri = null;
		if (file.exists()) {
			uri = file.toURI();
		}
		return uri;
	}

}
